﻿@using Blazorise
@using Blazorise.Utilities
@using System.Threading;
@inherits BaseInputComponent<string>
<Addons>
    <Addon AddonType="AddonType.Body">
        <Validation Validator="@(Validator ?? ValidationRule.IsNotEmpty)" AsyncValidator="@AsyncValidator">
            <TextEdit Role="@_passwordTextRole" Text="@Password" TextChanged="PasswordChanged">
            </TextEdit>
        </Validation>
    </Addon>
    <Addon AddonType="AddonType.End">
        <Button Color="Color.Secondary" Clicked="@(() => ChangePasswordTextRole(null))"><Icon Name="IconName.EyeSlash" /></Button>
    </Addon>
    <Addon AddonType="AddonType.End">
        <Button Color="Color.Secondary" Clicked="GenerateRandomPassword"><Icon Name="IconName.Random" /></Button>
    </Addon>
</Addons>
@code {

    /// <summary>
    /// Gets or sets the password inside the input field.
    /// </summary>
    [Parameter] public string Password { get; set; }

    /// <summary>
    /// Occurs after password has changed.
    /// </summary>
    [Parameter] public EventCallback<string> PasswordChanged { get; set; }

    /// <summary>
    /// Set the length of randomly generated password
    /// </summary>
    [Parameter] public int? Length { get; set; }

    /// <summary>
    /// Set characters for randomly generated password
    /// </summary>
    [Parameter] public string Characters { get; set; }


    /// <summary>
    /// Validation handler used to validate selected value.
    /// </summary>
    [Parameter] public Action<ValidatorEventArgs> Validator { get; set; }

    /// <summary>
    /// Asynchronously validates the selected value.
    /// </summary>
    [Parameter] public Func<ValidatorEventArgs, CancellationToken, Task> AsyncValidator { get; set; }

    private TextRole _passwordTextRole = TextRole.Text;
    private static Random random = new Random();


    protected override string InternalValue { get => Password; set => Password = value; }


    protected override Task OnInternalValueChanged(string value)
    {
        return PasswordChanged.InvokeAsync(value);
    }

    protected override Task<ParseValue<string>> ParseValueFromStringAsync(string value)
    {
        return Task.FromResult(new ParseValue<string>(true, value, null));
    }

    private void ChangePasswordTextRole(TextRole? textRole)
    {
        if (textRole == null)
        {
            ChangePasswordTextRole(_passwordTextRole == TextRole.Password ? TextRole.Text : TextRole.Password);
        }
        else
        {
            _passwordTextRole = textRole.Value;
        }
    }

    private async Task GenerateRandomPassword()
    {
        _passwordTextRole = TextRole.Text;
        await PasswordChanged.InvokeAsync(GetRandomPassword());
    }

    private string GetRandomPassword()
    {
        Length = Length.HasValue ? Length : 6;
        Characters = !Characters.IsNullOrEmpty() ? Characters : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghizklmnopqrstuvwxyz_-{}[]!@#$%^&*();'=+<>,.|?0123456789";

        return new string(
            Enumerable.Repeat(Characters, Length.Value)
                .Select(s => s[random.Next(s.Length)])
                .ToArray()
        );
    }
}
